#include <iostream>
#include <typeinfo>
#include <cassert>
#include <unistd.h>
#include <any>

class Any
{
public:
    Any()
        :_content(nullptr)
    {}

    template<class T>
    Any(const T& val)
        :_content(new placeholder<T>(val))
    {}

    Any(const Any& other)
        :_content(other._content ? other._content->clone() : nullptr)
    {}

    ~Any()
    {
        delete _content;
    }

    Any& swap(Any& other)
    {
        std::swap(_content, other._content);
        return *this;
    }

    template<class T>
    T* get()  // 返回子类对象保存的数据指针
    {
        // 要获取的数据类型必须和保存的数据类型一致
        assert (typeid(T) == _content->type());
            
        return &((placeholder<T>*)_content)->_val;
    }

    template<class T>
    Any& operator=(const T& val)   // 赋值运算符的重载函数
    {
        // 给val构造一个临时对象,和我们当前的容器进行指针交换,临时对象释放的时候,原先保存的数据也就被释放
        Any(val).swap(*this);
        return *this;
    }

    Any& operator=(const Any& other)
    {
        Any(other).swap(*this);
        return *this;
    }

private:
    class holder
    {
    public:
        virtual ~holder() {}

        virtual const std::type_info& type() = 0;

        virtual holder* clone() = 0;
    };

    template<class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T& val)
            :_val(val)
        {}

        virtual const std::type_info& type() override // 过去子类对象保存的数据类型
        {
            return typeid(T);
        }

        virtual holder* clone() override // 针对当前的对象自身, 克隆除一个新的子类对象
        {
            return new placeholder<T>(_val);
        }
    public:
        T _val;
    };
    holder* _content;
};

class Test
{
public:
    Test()
    {
        std::cout << "构造" << std::endl;
    }

    Test(const Test& t)
    {
        std::cout << "拷贝" << std::endl;
    }

    ~Test()
    {
        std::cout << "析构" << std::endl;
    }
};

int main()
{
    // Any a;
    // a = 10;
    // int* pa = a.get<int>();
    // std::cout << *pa << std::endl;

    // a = std::string("nihao");
    // std::string* ps = a.get<std::string>();
    // std::cout << *ps << std::endl;

    // // 代码段, 除了代码段,生命周期结束
    // {
    //     Any a;
    //     Test t;
    //     a = t;
    // }

    // while (1)
    //     sleep(1);


    // C++17中有any这个容器   头文件#include <any>
    std::any a = 10;
    int* pi = std::any_cast<int>(&a);
    std::cout << *pi << std::endl;
    a = std::string("hello");
    std::string* ps = std::any_cast<std::string>(&a);
    std::cout << *ps << std::endl;
    return 0;
}
